/**
 * \file syscall.h
 * \brief System call definitions
 * \author Corey Tabaka
 *
 * Copyright (C) Corey Tabaka 2007.
 * All rights reserved.
 */

/*
   Copyright 2007 Corey Tabaka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#ifndef __USER_SYSCALL_H__
#define __USER_SYSCALL_H__

#include <ktypes.h>

/*
 * System call function IDs
 */
enum {
	SYSCALL_NOP=0,
	SYSCALL_PROCESS,
	SYSCALL_THREAD,
	SYSCALL_MUTEX,
	SYSCALL_MESSAGE,
	SYSCALL_MEMORY,
	SYSCALL_MODULE,
	SYSCALL_INTERRUPT,
	SYSCALL_TIMER,
	SYSCALL_PCI,
	SYSCALL_RTC,
	SYSCALL_VAR,
	SYSCALL_VFS,
	SYSCALL_DEBUG,
	SYSCALL_PEAR,
	
	NUM_SYSCALLS
};

// Subfunctions for SYSCALL_MODULE
enum {
	SYSCALL_MODULE_LOAD,
	SYSCALL_MODULE_UNLOAD,
};

// Subfunctions for SYSCALL_MEMORY
enum {
	SYSCALL_MEMORY_MALLINFO,
	SYSCALL_MEMORY_PAGEINFO,
};

// Subfunctions for SYSCALL_VAR
enum {
	SYSCALL_VAR_IS_KEY,
	SYSCALL_VAR_GET_STRING,
	SYSCALL_VAR_GET_INT,
	SYSCALL_VAR_SET_STRING,
	SYSCALL_VAR_SET_INT,
	SYSCALL_VAR_CREATE_STRING,
	SYSCALL_VAR_CREATE_INT,
};

// Subfunctions for SYSCALL_VFS
enum {
	SYSCALL_VFS_REGISTER_MESSAGE_QUEUE,
	SYSCALL_VFS_UNREGISTER_MESSAGE_QUEUE,
	SYSCALL_VFS_OPEN,
	SYSCALL_VFS_READ,
	SYSCALL_VFS_WRITE,
	SYSCALL_VFS_CLOSE,
	SYSCALL_VFS_SEEK,
	SYSCALL_VFS_TELL,
	SYSCALL_VFS_PARAM,
	SYSCALL_VFS_STATUS,
};

// Subfunctions for SYSCALL_PEAR
enum {
	SYSCALL_PEAR_REG_CPU_STATE,
	SYSCALL_PEAR_SET_DEC,
	SYSCALL_PEAR_GET_DEC,
	SYSCALL_PEAR_GET_TB,
	SYSCALL_PEAR_SET_TB,
	SYSCALL_PEAR_GET_HOST_TICKS_PER_SEC,
	SYSCALL_PEAR_GET_SHIFT_DIV,
	SYSCALL_PEAR_SETUP_TIMEBASE,
};

// Subfunctions for SYSCALL_RTC
enum {
	SYSCALL_RTC_GET_TIME,
};

// Subfunctions for SYSCALL_MESSAGE
enum {
	SYSCALL_MESSAGE_SEND_PULSE,
	SYSCALL_MESSAGE_RECEIVE_PULSE,
	SYSCALL_MESSAGE_SEND,
	SYSCALL_MESSAGE_RECEIVE,
	SYSCALL_MESSAGE_REPLY,
	SYSCALL_MESSAGE_PIPE_CREATE,
	SYSCALL_MESSAGE_PIPE_DESTROY,
};

// Subfunctions for SYSCALL_DEBUG
enum {
	SYSCALL_DEBUG_BURN,
	SYSCALL_DEBUG_MEMORY,
	SYSCALL_DEBUG_LIST_TASKS,
	SYSCALL_DEBUG_CONTEXT_SWITCH_TIME,
	SYSCALL_DEBUG_RESCHEDULE_TIME,
	SYSCALL_DEBUG_MALLINFO,
	SYSCALL_DEBUG_PAGEINFO,
};

// Subfunctions for SYSCALL_INTERRUPT
enum {
	SYSCALL_INTERRUPT_ATTACH,
	SYSCALL_INTERRUPT_DETACH,
	SYSCALL_INTERRUPT_MASK,
	SYSCALL_INTERRUPT_UNMASK,
};

// Subfunctions for SYSCALL_TIMER
enum {
	SYSCALL_TIMER_GET_TICKS,
	SYSCALL_TIMER_GET_HI_RES_TICKS,
	SYSCALL_TIMER_GET_MILLIS,
	SYSCALL_TIMER_GET_FREQUENCY,
	SYSCALL_TIMER_CREATE_TIMER,
	SYSCALL_TIMER_DELETE_TIMER,
	SYSCALL_TIMER_SET_TIMER,
	SYSCALL_TIMER_GET_CPU_TICKS_PER_SEC,
	SYSCALL_TIMER_GET_CPU_TICKS_PER_MICRO,
	SYSCALL_TIMER_GET_MICRO_TIME,
};

// Subfunctions for SYSCALL_PCI
enum {
	SYSCALL_PCI_FIND_DEVICE,
	SYSCALL_PCI_FIND_CLASS_CODE,
	SYSCALL_PCI_READ_CONFIG_BYTE,
	SYSCALL_PCI_READ_CONFIG_WORD,
	SYSCALL_PCI_READ_CONFIG_DWORD,
	SYSCALL_PCI_WRITE_CONFIG_BYTE,
	SYSCALL_PCI_WRITE_CONFIG_WORD,
	SYSCALL_PCI_WRITE_CONFIG_DWORD,
};

// Subfunctions for SYSCALL_TASK
enum {
	SYSCALL_THREAD_YIELD=0,
	SYSCALL_THREAD_NEW,
	SYSCALL_THREAD_EXIT,
	SYSCALL_THREAD_KILL,
	SYSCALL_THREAD_JOIN,
	SYSCALL_THREAD_WAIT,
	SYSCALL_THREAD_NOTIFY,
	SYSCALL_THREAD_SLEEP,
	SYSCALL_THREAD_USLEEP,
	SYSCALL_THREAD_GET_TID,
	SYSCALL_THREAD_INFO,
	SYSCALL_THREAD_GET_LOCAL,
	SYSCALL_THREAD_SET_LOCAL,
	SYSCALL_THREAD_NEW_KEY,
	SYSCALL_THREAD_FREE_KEY,
	SYSCALL_THREAD_STACK_CHECK,
	SYSCALL_THREAD_ACQUIRE,
	SYSCALL_THREAD_PA_FROM_EA,
};

#if 1

extern "C"
uint64 syscall(uint32 arg, ...);

extern "C"
uint64 syscall64(uint32 arg, ...);

extern "C"
uint32 syscall32(uint32 arg, ...);

#else

static inline uint64 syscall(uint32 arg, ...) {
	uint32 low, high;
	
	__asm__ __volatile__ (
		"int $0x30\n\t"
		"mov %%eax,%0\n\t"
		"mov %%edx,%1\n\t"
		: "=r" (low), "=r" (high)
		:
		: "ax", "dx"
	);
	
	return ((uint64) high << 32) | low;
}

#endif

// common syscall macros

// thread syscalls
#define SLEEP(millis) syscall(SYSCALL_THREAD, SYSCALL_THREAD_SLEEP, (millis))
#define USLEEP(micros) syscall(SYSCALL_THREAD, SYSCALL_THREAD_USLEEP, (micros))
#define WAIT() syscall(SYSCALL_THREAD, SYSCALL_THREAD_WAIT)
#define YIELD() syscall(SYSCALL_THREAD, SYSCALL_THREAD_YIELD)
#define NOTIFY(tid) syscall(SYSCALL_THREAD, SYSCALL_THREAD_NOTIFY, (tid))
#define EXIT(status) syscall(SYSCALL_THREAD, SYSCALL_THREAD_EXIT, (status))
#define THREAD(func, arg, name) syscall(SYSCALL_THREAD, SYSCALL_THREAD_NEW, \
	(func), (arg), (name))

#endif
